home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 27 / CU Amiga Magazine's Super CD-ROM 27 (1998)(EMAP Images)(GB)[!][issue 1998-10].iso / CUCD / Programming / JForth / Extras / ODE / obj_binding < prev    next >
Encoding:
Text File  |  1992-01-22  |  7.8 KB  |  339 lines

  1. \ BINDING for Object Oriented Development Environment
  2. \
  3. \ This code provides words for binding a message to the appropriate
  4. \ method for an object.  Binding can occur at compile time ( "EARLY" ),
  5. \ or at run time, ( "LATE" )
  6. \
  7. \ Author: Phil Burk
  8. \ Copyright 1986 Phil Burk
  9. \
  10. \ MOD: PLB 11/29/86 Added MAC RO calls.
  11. \   For relocating systems, like on the MAC, relocatable tokens
  12. \   are stored in the dictionary, and absolute addresses are used at
  13. \   run time (when possible ).  The object stack contains absolute
  14. \   addresses.  The CFAs for methods are stored as relocatable tokens.
  15. \ MOD: PLB 5/13/87 Change OS-STACK-PTR to OSSTACKPTR for Mac
  16. \ MOD: PLB 5/24/87 Compile time check for Illegal Method.
  17. \ MOD: PLB 9/6/87 Add binding for Instance Objects.
  18. \ MOD: PLB 9/8/87 Preshift late bound offset in OB.LATE.BIND
  19. \      mdh 7/2/88 changed appropriate 'literal's to 'aliterals's
  20. \ MOD: PLB 7/25/88 USE OB.OBJ->CFA_BASE in OB.BIND.RUN
  21. \ MOD: PLB 11/27/90 Warn if recursive call to self.
  22. \ 00001 PLB 10/24/91 Allow binding to local variables.
  23. \ 00002 PLB 11/12/91 Call LOCAL.REFERENCE to force fetch.
  24. \ 00003 PLB 1/22/92 Assembled OB.BAD.CLASS? and added odd check.
  25.  
  26. ANEW TASK-OBJ_BINDING
  27.  
  28. ( Bind a method found in a CFA array. )
  29. ( Object base holds a pointer to an array of method CFAS )
  30. : OB.OBJ->CFA_BASE  ( use_obj_base -- use_cfa_base )
  31.     @  rel->use  ( relocate rel_cfa_base )
  32. ;
  33.  
  34. : OB.OBJ->CLASS  ( use_obj_base -- use_class_base )
  35.     @ rel->use ob_cfas -
  36. ;
  37.  
  38. : OB.CFA@ ( use_obj_base method_index -- rel_method_cfa , CFA for method )
  39.     cell* swap @ rel->use
  40.     + @
  41. ;
  42.  
  43. \ Error Checking for binding --------------------------------------
  44. : OB.VALID?  ( rel_object -- true_if_ok )
  45.     rel->use ob.obj->class
  46.     dup 1 and 0= ( is it even? )
  47.     IF ..@ ob_valid_key ob_valid.key =
  48.     ELSE drop FALSE
  49.     THEN
  50. ;
  51.  
  52. host=amiga .IF \ 00003
  53. ASM OB.BAD.CLASS? ( use_class_base -- bad? )
  54.         BTST        #0,D7        \ is it odd?
  55.         BNE            1$
  56.         MOVE.L        [ob_valid_key](org,tos),d7
  57.         CMP.L        #[ob_valid.key],d7    \ does key match?
  58.         BNE            1$
  59.         MOVEQ.L        #0,TOS
  60.         RTS
  61. 1$:        MOVEQ.L        #-1,TOS
  62.         RTS
  63. END-CODE
  64.  
  65. .ELSE
  66.  
  67. : OB.BAD.CLASS? ( use_class_base -- bad? )
  68.     dup 1 and
  69.     IF
  70.         drop true
  71.     ELSE
  72.         ..@ ob_valid_key ob_valid.key = NOT
  73.     THEN
  74. ;
  75. .THEN
  76.  
  77. : OB.CHECK.CLASS  ( use_class_base -- , abort if not a class )
  78.     ob.bad.class?
  79.     IF
  80.         " OB.CHECK.CLASS" " Not an ODE object or class!"
  81.         er_fatal er.report
  82.     THEN
  83. ;
  84.  
  85. : OB.CHECK.METHOD  ( method_index use_class_base -- , abort if bad method )
  86.     ..@ ob_#methods >
  87.     IF   " OB.CHECK.METHOD" " Method not supported for that object!"
  88.         er_fatal er.report
  89.     THEN
  90. ;
  91.  
  92. : OB.CHECK.BIND ( use_obj_base method_index -- , abort if bad )
  93.     swap ob.obj->class
  94.     dup ob.check.class
  95.     ob.check.method
  96. ;
  97.  
  98. \ DO compile time checking for illegal methods.
  99. : OB.CHECK.ILLEGAL ( rel_method_cfa -- )
  100.     rel->use 'c ob.bad.method =
  101.     IF " OB.CHECK.ILLEGAL" " Method not defined for this class."
  102.         er_fatal er.report
  103.     THEN
  104. ;
  105.  
  106. \ Compile code to execute method for an object. ---------------
  107. #HOST_AMIGA_JFORTH .IF
  108. : OB.BIND.CFA  ( use_obj_base rel_method_cfa -- , binds method to object )
  109.     dup ob.check.illegal swap
  110.     STATE @ IF
  111.         [compile] aliteral
  112.         compile os.push
  113.         calladr,
  114.         compile os.drop
  115.     ELSE
  116.         os.push
  117.         execute  os.drop
  118.     THEN
  119. ;
  120.  
  121. : OB.BIND.INSTANCE.CFA ( instance_offset rel_method_cfa -- )
  122.     dup ob.check.illegal swap
  123.     state @
  124.     IF  [compile] literal
  125.         compile os+push
  126.         calladr,
  127.         compile os.drop
  128.     ELSE
  129.         os+push
  130.         execute os.drop
  131.     THEN
  132. ;
  133.  
  134. .THEN
  135.  
  136. #HOST_MAC_H4TH .IF
  137. : (OB.EXEC.METHOD)  ( rel_method_cfa rel_obj_base -- )
  138.     rel->use os.push ro.execute os.drop
  139. ;
  140.  
  141. : OB.BIND.CFA  ( use_obj_base rel_method_cfa -- , binds method to object )
  142.     dup ob.check.illegal
  143.     STATE @ IF
  144.         [compile] literal  ( cfa )
  145.         use->rel [compile] literal    ( obj_base )
  146.         compile (ob.exec.method)
  147.     ELSE
  148.         swap os.push ro.execute os.drop
  149.     THEN
  150. ;
  151.  
  152. : (OB.EXEC.METHOD.I)  ( rel_method_cfa offset -- )
  153.     os+push ro.execute os.drop
  154. ;
  155.  
  156. : OB.BIND.INSTANCE.CFA ( instance_offset rel_method_cfa -- )
  157.     dup ob.check.illegal
  158.     state @
  159.     IF
  160.         [compile] literal  ( cfa )
  161.         [compile]  literal  ( offset )
  162.         compile (ob.exec.method.i)
  163.     ELSE
  164.         swap os+push
  165.         ro.execute os.drop
  166.     THEN
  167. ;
  168. .THEN
  169.  
  170. variable OB-IF-CHECK-BIND
  171. variable OB-CURRENT-MIND  \ currently compiling method index
  172.  
  173.  
  174. #host_amiga_jforth .IF
  175.  
  176. max-inline @ 200 max-inline ! ( optimize !! )
  177. : OB.CHECK.BIND.RUN ( rel_obj method_index*4 -- rel_obj method_index*4 )
  178.     2dup 4/ ob.check.bind
  179. ;
  180. max-inline !
  181.  
  182. ASM OB.BIND.RUN ( rel_obj method_index*4 -- , run time binding act)
  183.     move.l    [ ob-if-check-bind here - 2- ](pc),d0
  184.     beq.s    1$
  185.     callcfa    ob.check.bind.run
  186. 1$:    move.l    tos,d2        \ D2 = method*4
  187.     move.l    (dsp)+,tos
  188.     move.l    tos,d3        \ D3 = rel_obj
  189.     callcfa    os.push
  190.     move.l  $0(org,d3.l),D0    \ D0 = rel address of CFA table
  191.     add.l    d2,d0
  192.     move.l  $0(org,d0.l),D1    \ D1 = rel address of method
  193.     jsr        $0(org,d1.l)
  194.     callcfa    os.drop
  195.     rts
  196. END-CODE
  197.  
  198. .ELSE
  199.  
  200. : OB.BIND.RUN  ( rel_obj_base method_index*4 -- , run time binding act)
  201.     >r rel->use
  202.     ob-if-check-bind @
  203.     IF dup r@ 4/ ob.check.bind
  204.     THEN
  205.     dup os.push   ( push object onto object stack )
  206.     @ rel->use r> +  ( index to method cfa )
  207.     @ rel->use execute   ( Perform method on object. )
  208.     os.drop
  209. ;
  210. .THEN
  211.  
  212. : OB.LATE.BIND  ( [rel_obj_base] method_index -- , do late binding of method )
  213. \  rel_obj_base not present at compile time.
  214.     STATE @
  215.     IF
  216.         cell* ( preshift for faster run time )
  217.         [compile] literal  ( save method index for late binding )
  218.         compile ob.bind.run
  219.     ELSE  cell* ob.bind.run
  220.     THEN
  221. ;
  222.  
  223. : SELF ( -- rel_obj_base, of_self )
  224.     os.copy  use->rel ( %R )
  225. ;
  226.  
  227. EXISTS? [] NOT .IF
  228. : []   ( -- , use late binding if 'method: []' )
  229.     " OBJECT USE" " '[]' CAN ONLY BE AFTER A METHOD"
  230.         er_fatal  er.report
  231. ;
  232. .THEN
  233.  
  234. : SUPER ( --- , stub for superbinding )
  235.     " OBJECT USE" " 'SUPER' can only be used inside a METHOD definition"
  236.     er_fatal  er.report
  237. ;
  238.  
  239. \ Binding with super-dooper uses the method defined in a superclasses'
  240. \ superclass.
  241. : SUPER-DOOPER ( --- , stub for superbinding with skip )
  242.     " OBJECT USE"
  243.     " 'SUPER-DOOPER' can only be used inside a METHOD definition"
  244.     er_fatal  er.report
  245. ;
  246.  
  247.  
  248. #HOST_AMIGA_JFORTH .IF
  249. : OB.BIND.'BASE ( CFA -- , bind CFA to current object )
  250.     ?comp calladr,
  251. ;
  252. .THEN
  253.  
  254. #HOST_MAC_H4th .IF
  255. : OB.BIND.'BASE  ( rel_CFA -- , bind CFA to current object )
  256.     ?comp [compile] literal   compile ro.execute
  257. ;
  258. .THEN
  259.  
  260. \ These words work off of a variable that contains an use_cfa_base.
  261. : OB.BIND.VAR ( method_index cfa_base_variable -- , bind from that variable )
  262.     @ swap cell* + @  ( -- method_cfa )
  263.     dup ob.check.illegal
  264.     ob.bind.'base  ( %? )
  265. ;
  266.  
  267. : OB.BIND.INSTANCE ( method_index pfa_object_def -- )
  268.     dup ..@ obi_offset ( get offset )
  269.     -rot  ..@ obi_rel_class rel->use .. ob_cfas ( -- off mi acfas )
  270.     swap cell* + @
  271.     ob.bind.instance.cfa
  272. ;
  273.  
  274. : OB.BIND.NORMAL  ( method_index pfa_object -- )
  275.     dup rot 2dup ob.check.bind
  276.     ob.cfa@ ob.bind.cfa
  277. ;
  278.  
  279. : OB.EARLY.BIND  ( method_index cfa_object -- )
  280.     cfa->pfa
  281.     ob-state @ ob_def_class =
  282.     IF  dup ob-current-class @
  283.         ob.is.instance? ( Check to see if this is an Instance Object.)
  284.         IF ob.bind.instance
  285.         ELSE ob.bind.normal
  286.         THEN
  287.     ELSE ob.bind.normal
  288.     THEN
  289. ;
  290.  
  291. : OB.FIND.OBJECT  ( <object> -- cfa , abort if not found )
  292.     bl word find NOT
  293.     IF
  294.         >newline count type ."  ?" cr
  295.         " OB.FIND.OBJECT" " Object not found!"
  296.         er_fatal  er.report
  297.     THEN
  298. ;
  299.  
  300. : OB.CHECK.RECURSE  ( method_index -- , warn in recurse: self )
  301.     ob-current-mind @ =
  302.     IF
  303.         " OB.CHECK.RECURSE" " Recursive message to self!"
  304.         er_warning er.report
  305.         current-method @ id. ."  SELF" cr
  306.     THEN
  307. ;
  308.  
  309. : OB.BIND   ( method_index <object> -- , bind )
  310.     ob.find.object  ( -- mi cfa )
  311.     CASE  ( Different types of binding. )
  312. \ Assume rel_obj_base also on stack at runtime for late binding.
  313.         'c []
  314.         OF ob.late.bind
  315.         ENDOF
  316. \
  317. \ allow automatic late bind to locals 00001
  318.         'c local.reference
  319.         OF [compile] local.reference ob.late.bind \ 00002
  320.         ENDOF
  321. \
  322.         'c SELF
  323.         OF    dup ob.check.recurse
  324.             ob-self-cfas ob.bind.var
  325.         ENDOF
  326. \
  327.         'c SUPER
  328.         OF ob-super-cfas ob.bind.var
  329.         ENDOF
  330. \
  331.         'c SUPER-DOOPER
  332.         OF ob-dooper-cfas ob.bind.var
  333.         ENDOF
  334. \
  335. \ Bind named object.
  336.         ob.early.bind 0   ( needs zero for dropping )
  337.     ENDCASE
  338. ;
  339.